﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SocketSuperLib
{
    /// <summary>
    /// Socket 连接
    /// </summary>
    public class SocketClient: IClient
    {
        #region Socket
        private Socket m_sockClient;
        private string m_szServerIP = "";
        private int m_nPort = 0; 
        private int m_nConnOutTime = 4000;
        private AutoResetEvent m_vntConn;
        private Encoding encoding;
        /// <summary>
        /// 是否连接成功
        /// </summary>
        private bool m_bConnSucceed = false;
        private string m_szErrorMessage; 

        public SocketClient(string _ip,int _port)
        {
            m_szServerIP = _ip;
            m_nPort = _port; 
            this.m_vntConn = new AutoResetEvent(false);
            encoding = Encoding.GetEncoding("GBK");
        } 

        /// <summary>
        /// 得到返回信息
        /// </summary>
        /// <param name="byData"></param>
        /// <param name="byBuffer"></param>
        /// <returns></returns>
        private int SendAndReturnMsg(ref byte[] byData, ref BufferByte byBuffer,Boolean isShutdown)
        {
            //连接Socket
            Connect();
            if (!this.m_bConnSucceed) 
                return -1;

            byte[] temp = new byte[256];
            try
            {
                //发送信息
                this.m_sockClient.Send(byData);
                int num1 = 0;  
                num1 = this.m_sockClient.Receive(temp); 
                byBuffer.Push(temp,num1); 
                while (this.m_sockClient.Available != 0)
                {  
                    num1 = this.m_sockClient.Receive(temp);
                    byBuffer.Push(temp, num1); 
                }
                if (isShutdown)
                    this.CloseSocket();
            }
            catch(Exception ex)
            {
                this.m_szErrorMessage = ex.Message;
                return -1;
            }
            return 1;
        } 

        /// <summary>
        /// 连接Socket
        /// </summary> 
        /// <returns>1 成功 其他 失败</returns>
        private void Connect()
        { 
            if (this.m_sockClient == null)
            {
                this.m_sockClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this.m_sockClient.ReceiveBufferSize = 0x2000;
                this.m_sockClient.ReceiveTimeout = 0x3a98;
            }
            //关闭已经连接的Socket
            //CloseSocket();
            if (!this.m_bConnSucceed)
            {
                Thread thread1 = new Thread(new ThreadStart(this.ConnThread));
                thread1.Start();
                this.m_vntConn.WaitOne(this.m_nConnOutTime, true);
                this.m_vntConn.Reset(); 
            } 
        }

        /// <summary>
        /// 
        /// </summary>
        private void ConnThread()
        {
            try
            {
                this.m_sockClient.Connect(IPAddress.Parse(this.m_szServerIP), this.m_nPort);
                this.m_bConnSucceed = true;
            }
            catch (Exception exception1)
            {
                this.m_szErrorMessage = exception1.Message;
                this.m_bConnSucceed = false;
            }
            this.m_vntConn.Set();

        }

        /// <summary>
        /// 关闭Socket
        /// </summary>
        private void CloseSocket()
        {
            if (this.m_sockClient != null && this.m_sockClient.Connected)
            {
                try
                {
                    this.m_sockClient.Shutdown(SocketShutdown.Both);
                    this.m_sockClient.Close(); 
                }
                catch (Exception)
                {
                    this.m_bConnSucceed = true;
                }
            }
            this.m_sockClient = null;
            this.m_bConnSucceed = false; 
        }  
        #endregion

        /// <summary>
        /// 发送并获取返回信息
        /// </summary>
        /// <param name="sendMsg">发送数据</param>
        /// <param name="tryCount">尝试发送次数</param>
        /// <returns>返回数据 空串或有数据</returns>
        public string SendAndReturnMsg(string sendMsg, int iTryTimes)
        {
            return SendAndReturnMsg(sendMsg,iTryTimes,true);
        }

        /// <summary>
        /// 发送并获取返回信息(该方法关闭连接需要重新连接)
        /// </summary>
        /// <param name="sendMsg">发送数据</param>
        /// <param name="iTryTimes">尝试发送次数</param>
        /// <param name="isShutdown">是否关闭连接</param>
        /// <returns>返回数据 空串或有数据</returns>
        public string SendAndReturnMsg(string sendMsg, int iTryTimes, bool isShutdown)
        { 
            int num1 = 0;
            byte[] buffer1 = encoding.GetBytes(sendMsg + "\r");
            BufferByte buffer2 = new BufferByte();
            // 直到它联通了
            while (1 != num1 && iTryTimes-- >0)
            {
                buffer2.Clear(); 
                num1 = SendAndReturnMsg(ref buffer1, ref buffer2, isShutdown); 
                Thread.Sleep(100);
            }
            if (1 != num1)  // 中途出现问题 
                return "";
            // 4、收到同步的还书返回信息    
            return encoding.GetString(buffer2.ToArray()).Trim(); 
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <returns>1 成功 其他 失败</returns>
        public int Close()
        {
            CloseSocket();
            return this.m_bConnSucceed ? 0 : 1;
        }

        bool IClient.IConnect()
        {
            //连接Socket
            Connect();
            return this.m_bConnSucceed;
        }


        public string SendAndReturnMsg(string sendMsg)
        {
            return SendAndReturnMsg(sendMsg,1,true);
        }
    }
}
